#!/usr/bin/python3
# coding=utf-8

from check_log_grab.common import get_json, post_json, save_json
import redis
from loguru import logger as log
from configobj import ConfigObj
from datetime import datetime, timedelta


class WechatReptile(object):
    def __init__(self, config: dict):
        self.corp_id = config.get("corp_id", "")
        self.corp_secret = config.get("corp_secret", "")
        if self.corp_secret in "" and self.corp_secret in "":
            log.error(f"corp_id：{self.corp_id},  corp_secret：{self.corp_secret},请检查配置")
            exit()
        self.redis_ip = config.get("redis_ip", "localhost")
        self.redis_port = config.get("redis_port", 6379)
        self.redis_expire = config.get("redis_expire", 7199)

    def __access_token_net__(self):
        """
        获取网络上的access_token
        :return:
        """
        return get_json(
            f"https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={self.corp_id}&corpsecret={self.corp_secret}").get(
            'access_token', "")

    def __access_token_cache__(self, cfg_path="cache"):
        """
         获取本地access_token
         :param cfg_path:
         :return:
         """
        config = ConfigObj(cfg_path, encoding='UTF-8')
        try:
            if datetime.now() > datetime.fromtimestamp(int(config['DB']['time'])):
                return config['DB']['access_token']
        except KeyError:
            log.info("初始化缓存")
        at = self.__access_token_net__()
        config['DB'] = {'time': int((datetime.now() + timedelta(seconds=self.redis_expire)).timestamp()),
                        'access_token': at}
        config.write()
        return at

    def __get_access_token__(self):
        """
        获取access_token
        :return:
        """
        try:
            with redis.StrictRedis(host=self.redis_ip, port=self.redis_port)as conn:
                s = conn.get("access_token")
                if s is None:
                    at = self.__access_token_net__()
                    if len(at) > 0:
                        conn.set("access_token", at)
                        conn.expire("access_token", self.redis_expire)
                        log.info("access_token 已经更新！")
                        return at
                    else:
                        log.error("access_token获取失败，请检查原因")
                        exit()
                return s.decode('utf8')
        except Exception as err:
            log.error(err)
            return self.__access_token_cache__()

    def get_department(self, out_file=False, data_file="department.json"):
        """
        获取所有部门编号信息
        :param out_file:
        :param data_file:
        :return:
        """
        at = self.__get_access_token__()
        jd = get_json(f"https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token={at}")
        save_json(data_file, jd, out_file=out_file)
        return jd.get('checkindata', [])

    def get_userinfo(self, d_id: int, out_file=False, data_file="userinfo.json"):
        """
        获取指定部门员工信息
        :param d_id:department_id:
        :param out_file:
        :param data_file
        :return:json {
        errcode:返回码
        errmsg:对返回码的文本描述内容
        department:部门列表数据。
        id:创建的部门id
        name:部门名称，代开发自建应用需要管理员授权才返回；此字段从2019年12月30日起，对新创建第三方应用不再返回，2020年6月30日起，对所有历史第三方应用不再返回name，返回的name字段使用id代替，后续第三方仅通讯录应用可获取，未返回名称的情况需要通过通讯录展示组件来展示部门名称
        name_en:英文名称，此字段从2019年12月30日起，对新创建第三方应用不再返回，2020年6月30日起，对所有历史第三方应用不再返回该字段
        department_leader:部门负责人的UserID；第三方仅通讯录应用可获取
        parentid:父部门id。根部门为1
        order:在父部门中的次序值。order值大的排序靠前。值范围是[0, 2^32)
    }
        """
        at = self.__get_access_token__()
        jd = get_json(
            f"https://qyapi.weixin.qq.com/cgi-bin/user/simplelist?access_token={at}&department_id={d_id}&fetch_child=1")
        save_json(data_file, jd, out_file=out_file)
        return jd.get('checkindata', [])

    def get_check_in_data(self, start: int, end: int, u_ids: list, out_file=False, ch_type=3):
        """
           获取打卡记录数据
           :param start:获取打卡记录的开始时间。Unix时间戳
           :param end:获取打卡记录的结束时间。Unix时间戳
           :param u_ids:需要获取打卡记录的用户列表
           :param ch_type:打卡类型。1：上下班打卡；2：外出打卡；3：全部打卡
           :param out_file: 是否输出文件
           :return:json{
               errcode:返回码
               errmsg:对返回码的文本描述内容
               checkindata:[{
                   userid:用户id
                   groupname:打卡规则名称
                   checkin_type:打卡类型。字符串，目前有：上班打卡，下班打卡，外出打卡
                   exception_type:异常类型，字符串，包括：时间异常，地点异常，未打卡，wifi异常，非常用设备。如果有多个异常，以分号间隔
                   checkin_time:打卡时间。Unix时间戳
                   location_title:打卡地点title
                   location_detail:打卡地点详情
                   wifiname:打卡wifi名称
                   notes:打卡备注
                   wifimac:打卡的MAC地址/bssid
                   mediaids:打卡的附件media_id，可使用media/get获取附件
                   lat:位置打卡地点纬度，是实际纬度的1000000倍，与腾讯地图一致采用GCJ-02坐标系统标准
                   lng:位置打卡地点经度，是实际经度的1000000倍，与腾讯地图一致采用GCJ-02坐标系统标准
                   deviceid:打卡设备id
                   sch_checkin_time:标准打卡时间，指此次打卡时间对应的标准上班时间或标准下班时间
                   groupid:规则id，表示打卡记录所属规则的id
                   schedule_id:班次id，表示打卡记录所属规则中，所属班次的id
                   timeline_id:时段id，表示打卡记录所属规则中，某一班次中的某一时段的id，如上下班时间为9:00-12:00、13:00-18:00的班次中，9:00-12:00为其中一组时段
               }]}
               1.获取记录时间跨度不超过30天
               2.用户列表不超过100个。若用户超过100个，请分批获取
               3.有打卡记录即可获取打卡数据，与当前”打卡应用”是否开启无关
               4.标准打卡时间只对于固定排班和自定义排班两种类型有效
               5.接口调用频率限制为600次/分钟
           """
        json_para = {"opencheckindatatype": ch_type, "starttime": start, "endtime": end, "useridlist": u_ids}
        at = self.__get_access_token__()  # 调用接口凭证。必须使用打卡应用的Secret获取access_token
        print(at)
        log.info("开始下载企业微信打卡数据，请等待.....")
        jd = post_json(f"https://qyapi.weixin.qq.com/cgi-bin/checkin/getcheckindata?access_token={at}", jp=json_para)
        if len(jd.get('checkindata', [])) == 0:
            log.error("企业微信打卡数据下载失败，请检查参数！")
            return []
        log.info("企业微信打卡数据下载成功！")
        save_json(f"check_data-{start}_{end}.json", jd, out_file=out_file)
        return jd.get('checkindata', [])

    def __enter__(self):
        pass
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        pass


if __name__ == '__main__':
    print(WechatReptile({"corp_id": "ww418cfccde359a3da", "redis_ip": "localhost",
                         "corp_secret": "GkF0tLspDOVw2IKkDoEO1u-UXdeJDMTqD1bUh0UW8lM"}).__get_access_token__())
